
///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2009, Perry L Miller IV
//  All rights reserved.
//  BSD License: http://www.opensource.org/licenses/bsd-license.html
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
//  Node class for the registry.
//
///////////////////////////////////////////////////////////////////////////////

#include "Usul/Config/Config.h"
#include "Usul/Registry/Node.h"
#include "Usul/Registry/Visitor.h"

using namespace Usul::Registry;


///////////////////////////////////////////////////////////////////////////////
//
//  Constructor.
//
///////////////////////////////////////////////////////////////////////////////

Node::Node() : BaseClass(),
  _name(),
  _value(),
  _kids()
{
}


///////////////////////////////////////////////////////////////////////////////
//
//  Destructor.
//
///////////////////////////////////////////////////////////////////////////////

Node::~Node()
{
}


///////////////////////////////////////////////////////////////////////////////
//
//  Accept the visitor.
//
///////////////////////////////////////////////////////////////////////////////

void Node::accept ( Visitor *v )
{
  if ( 0x0 != v )
  {
    v->visit ( this );
  }
}


///////////////////////////////////////////////////////////////////////////////
//
//  Set the value.
//
///////////////////////////////////////////////////////////////////////////////

void Node::set ( const std::string &s )
{
  _value = s;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Set the value.
//
///////////////////////////////////////////////////////////////////////////////

void Node::set ( const char *s )
{
  this->set ( std::string ( ( 0x0 == s ) ? "" : s ) );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Get the value.
//
///////////////////////////////////////////////////////////////////////////////

std::string Node::get ( const std::string &defaultValue ) const
{
  return ( ( true == _value.empty() ) ? defaultValue : std::string ( _value ) );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Get the value.
//
///////////////////////////////////////////////////////////////////////////////

std::string Node::get ( const std::string &defaultValue, bool setValueIfEmpty )
{
  if ( ( true == _value.empty() ) && ( true == setValueIfEmpty ) )
  {
    this->set ( defaultValue );
  }

  return this->get ( defaultValue );
}


///////////////////////////////////////////////////////////////////////////////
//
//  Clear the database.
//
///////////////////////////////////////////////////////////////////////////////

void Node::clear()
{
  _value.clear();
  _kids.clear();
}


///////////////////////////////////////////////////////////////////////////////
//
//  Return the child with the name. Creates child nodes as needed.
//
///////////////////////////////////////////////////////////////////////////////

Node::RefPtr Node::_getNode ( const std::string &name )
{
  Guard ( _kids.mutex() );
  Children &kids ( _kids.getReference() );

  Children::iterator i ( kids.find ( name ) );
  Node::RefPtr child ( ( kids.end() == i ) ? 0x0 : i->second );
  if ( false == child.valid() )
  {
    child = Node::RefPtr ( new Node );
    child->name ( name );
    kids.insert ( Children::value_type ( name, child ) );
  }
  return child;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Operator to return the child with the name. Creates child nodes as needed.
//
///////////////////////////////////////////////////////////////////////////////

Node &Node::operator [] ( const std::string &name )
{
  Guard ( _kids.mutex() );
  Children::iterator i ( _kids.getReference().find ( name ) );
  Node::RefPtr child ( this->_getNode ( name ) );
  return *child;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Operator to return the child with the path. Creates child nodes as needed.
//
///////////////////////////////////////////////////////////////////////////////

Node &Node::operator [] ( const Node::Path &path )
{
  Node::RefPtr child ( this );

  for ( Node::Path::const_iterator i = path.begin(); i != path.end(); ++i )
  {
    child = child->_getNode ( *i );
  }

  return *child;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Return the child with the name. No new nodes are created.
//
///////////////////////////////////////////////////////////////////////////////

Node::RefPtr Node::find ( const std::string &name ) const
{
  Guard ( _kids.mutex() );
  const Children &kids ( _kids.getReference() );
  Children::const_iterator i ( kids.find ( name ) );
  Node::RefPtr child ( ( kids.end() == i ) ? 0x0 : i->second );
  return child;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Get a copy of the children.
//
///////////////////////////////////////////////////////////////////////////////

Node::Children Node::children() const
{
  return _kids;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Get the name.
//
///////////////////////////////////////////////////////////////////////////////

std::string Node::name() const
{
  return _name;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Set the name.
//
///////////////////////////////////////////////////////////////////////////////

void Node::name ( const std::string &n )
{
  _name = n;
}


///////////////////////////////////////////////////////////////////////////////
//
//  Return the number of children.
//
///////////////////////////////////////////////////////////////////////////////

unsigned int Node::numChildren() const
{
  Guard ( _kids.mutex() );
  return _kids.getReference().size();
}
